package client

import (
	"log"
	"net"
	"syproxy/library"
	"syproxy/service"
	"time"
)

func Run(l, r, authPw string) {
	for {
		container := library.NewContainer()
		remote := service.NewService()

		var err error
		remote.Conn, err = net.Dial("tcp", r)
		if err != nil {
			log.Fatal(err)
		}

		// 验证身份
		err = service.AuthToServer(remote, authPw)
		if err != nil {
			log.Fatal(err)
		}

		//go heatBeating(remote)
		go remote.Read()
		go handleServer(remote, container)

		// 等待远方调用
		for {
			id := <-remote.Open
			local := service.NewService()
			local.Id = id
			var err error
			local.Conn, err = net.Dial("tcp", l)
			if err != nil {
				log.Printf("Open tcp failed local: %v", local)
				continue
			}
			log.Printf("Open tcp: id: %v", local.Id)
			container.Push(local.Id, local)
			go handle(remote, local, container)
			go local.ReadRaw()
		}

		// 5秒后重试
		log.Println("服务断线重连，5s后重启")
		time.Sleep(time.Duration(5) * time.Second)
	}
}

func handleServer(s *service.Service, container *library.Container) {
	for {
		select {
		case content := <-s.Recv:
			c := container.GetService(content.Id)
			library.HandleRead(content, s, c)
		case <-s.CloseMe:
			s.Close()
			container.RemoveAll()
			return
		case id := <-s.CloseOther:
			c := container.GetService(id)
			c.Close()
		}
	}
}

// 处理互交
func handle(s, c *service.Service, container *library.Container) {
	for {
		select {
		case content := <-c.Recv:
			s.Write(content.Data, []byte(content.Id))
		case <-c.CloseMe:
			c.Close()
			container.Remove(c.Id)
			s.Write([]byte("close"), []byte(c.Id))
			return
		case <-c.CloseOther:
			// 这种情况不会发生
			c.Close()
			return
		}
	}
}

// heatBeating
func heatBeating(remote *service.Service) {
	for {
		// FIXME::
		remote.Write([]byte("ping"), []byte(""))
		time.Sleep(time.Duration(29) * time.Second)
	}
}
